package br.com.academia.DAO;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import br.com.academia.annotations.Coluna;
import br.com.academia.annotations.Id;
import br.com.academia.annotations.Tabela;
import br.com.academia.beans.Aluno;
import br.com.academia.util.ConnectionFactory;

public class DAOGenerico<T> {
	Connection connection;
	private Class<?> classe;
	
	public DAOGenerico(Connection connection, Class classe) {
		this.connection = connection;
		this.classe = classe;
	}
	
	public DAOGenerico(Connection connection) {
		this.connection = connection;
	}
	
	public void cadastrar(T tipoClasse) throws Exception {
		
		Class<?> classe = tipoClasse.getClass();
		
		StringBuilder query = new StringBuilder("Insert into " + classe.getAnnotation(Tabela.class).nomeTabela() + " (");
		
		for (Field field : classe.getDeclaredFields()) {
            field.getAnnotation(Coluna.class);
            if (field.getAnnotation(Coluna.class).referenciaExterna()) {
            	continue;
            }
            query.append(field.getAnnotation(Coluna.class).nomeBanco() + ", ");
        }
		
		query.deleteCharAt(query.length() -2);
		query.append(") values (");
		
		for (Field field : classe.getDeclaredFields()) {
            if (field.getAnnotation(Coluna.class).referenciaExterna()) {
            	continue;
            }
			query.append("?, ");
        }
		
		query.deleteCharAt(query.length() -2);
		query.append(")");
		
        PreparedStatement stm = connection.prepareStatement(query.toString());
        
        int contador = 1;
        
        for(Field field : classe.getDeclaredFields()) {
        	 if (field.getAnnotation(Coluna.class).referenciaExterna()) {
             	continue;
             }
        	String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
        	stm.setObject(contador, classe.getMethod(methodName).invoke(tipoClasse));
        	contador++;
        }
        
		stm.execute();

        connection.close();
	}
	
	public void alterar(T tipoClasse, String chaveAlteracao) throws Exception {
		
		Class<?> classe = tipoClasse.getClass();
		
		StringBuilder query = new StringBuilder("Update " + classe.getAnnotation(Tabela.class).nomeTabela() + " set ");
		
		for (Field field : classe.getDeclaredFields()) {
            Coluna coluna = field.getAnnotation(Coluna.class);
            if (coluna.referenciaExterna()) {
            	continue;
            }
            if(coluna.nomeBanco().equals(chaveAlteracao)) {
            	continue;
            }
            query.append(coluna.nomeBanco() + " =  ?, ");
        }
		query.deleteCharAt(query.length() -2);
		
		query.append(" where " + chaveAlteracao + " =  ? ");
		
        PreparedStatement stm = connection.prepareStatement(query.toString());
        
        int contador = 1;
        
        for(Field field : classe.getDeclaredFields()) {
        	Coluna coluna = field.getAnnotation(Coluna.class);
            if (coluna.referenciaExterna()) {
            	continue;
            }
        	String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
            if(methodName.equalsIgnoreCase("get" + chaveAlteracao)) {
            	continue;
            }
        	stm.setObject(contador, classe.getMethod(methodName).invoke(tipoClasse));
        	contador++;
        }
        
        stm.setObject(contador, classe.getMethod("get" + chaveAlteracao.substring(0, 1).toUpperCase() + chaveAlteracao.substring(1)).invoke(tipoClasse));
        
		stm.execute();
        connection.close();
	}
	
	public void excluir(T tipoClasse, String chaveExclusao) throws Exception {
		
		Class<?> classe = tipoClasse.getClass();
		
		StringBuilder query = new StringBuilder("Delete from " + classe.getAnnotation(Tabela.class).nomeTabela());
		query.append(" where " + chaveExclusao + " =  ? ");
		
        PreparedStatement stm = connection.prepareStatement(query.toString());
        stm.setObject(1, classe.getMethod("get" + chaveExclusao.substring(0, 1).toUpperCase() + chaveExclusao.substring(1)).invoke(tipoClasse));
        
		stm.execute();

        connection.close();
	}

}
